Skip to main content

Lifecycle functions

组件初始化逻辑

从调用类组件 new MyComponent()开始,类组件内部发生的事情

1. 初始化属性 && 规则校验

  • 先规则校验,校验完毕后,再处理属性的其他操作! !

  • 方案一

    constructor(props) {
    super(props); //会把传递进来的属性挂载到this实例上
    console.log(this.props); //获取到传递的属性
    }
  • 方案二

    • 即便我们自己不在constructor中处理或者constructor都没写,在constructor处理完毕后,React内部也会把传递的props挂载到实例上。
    • 在其他的函数中,只要保证this是实例,就可以基于this.props获取传递的属性!
    • 同样this.props获取的属性对象也是只读的:object.isFrozen(this.props)==true

2. 初始化状态

  • 状态初始化
    • 后期修改状态,可以触发视图的更新
    • 需要手动初始化,如果我们没有去做相关的处理,则默认会往实例上挂载一个state,初始值是null:this.state=null
  • 修改状态
    • 控制视图更新this.state.xxx=xxx : 这种操作仅仅是修改了状态值,但是无法让视图更新;
    • 想让视图更新需要基于React.Component.prototype提供的方法操作:
      // this.setstate(partialstate) 既可以修改状态,
      // 也可以让视图更新-推荐
      this.setState({
      // partialState:部分状态
      // xxx:xxx
      })
      // 强制更新,不管state有没有变化,强制更新视图
      this.forceUpdate()

3. 触发 componentwillMount(第一次染前)

钩子函数

在程序运行到某个阶段,我们可以基于提供一个处理函数,让开发者在这个阶段做一些自定义的事情

tip
此周期函数,目前是不安全的[虽然可以用,但是未来可能要被移除了,所以不建议使用- 控制会抛出黄色警告 为了不抛出警告,我们可以暂时用 UNSAFE componentwillMountj - 如果开启了React.StrictMode,则我们使用 UNSAFE_componentWiLlMount - 这样的周期函数,控制台会直接抛出红色警告错误! !

4. 触发 render 函数

  • 将virtualDOM变为actualDOM

5. 触发 componentDidMount函数

  • 已经把virtualDOM变为真实DOM了,所以我们可以获取真实DOM了
  • ...

组件更新逻辑

组件更新的逻辑 [当修改了相关状态,组件会更新

1. 触发 shouldComponentUpdate

周期函数: 是否允许更新
shouldComponentUpdate(nextProps, nextState) {
// nextState:存储要修改的最新状态
// this.state:存储的还是修改前的状态此时状态还没有改变
console.log(this.state, nextState)
// 此周期函数需要返回true/false
// 返回true: 允许更新,会继续执行下一个操作
// 返回false: 不允许更新,接下来啥都不处理
return true
}

2. 触发 componentwillUpdate 周期函数: 更新之前

tip
  • 此周期函数也是不安全的
  • 在这个阶段,状态还没有被修改

3. 修改状态值

  • 让this.state.xxx改为最新的值

4. 触发 render 周期函数: 组件更新

  • 按照最新的状态/属性,编译JSX=>virtualDOM
  • DOM-DIFF:和上一次渲染出来的virtualDOM进行对比
  • 把差异的部分进行渲染为真实的DOM

5. 触发 componentDidUpdate

组件更新完毕特殊说明
  • 如果我们是基于 this.forceupdate() 强制更新视图,会跳过 shouldComponentUpdate 周期函数的校验,直接从WillUpdate 开始进行更新
  • 也就是: 视图一定会触发更新!

render函数

  • render函数在渲染的时候,如果type是:
    • 字符串: 创建一个标签
    • 普通函数: 把函数执行,并且把props传递给函数
    • 构造函数: 把构造函数基于new执行 也就是创建类的一个实例],也会把解析出来的props传递过去
      • 每调用一次类组件都会创建一个单独的实例(如果是PureComponet做shallow compare,差异才reRender)
      • 把在类组件中编写的render函数执行,把返回的jsx virtualDOM,当做组件视图进行染!!

父组件更新导致子组件更新

  • 触发 componentwillReceiveProps 周期函数

    tip
    • 接收最新属性之前
    • 周期函数是不安全的
    UNSAFE_componentWillReceiveProps(nextProps) {
    // this.props:存储之前的属性
    // nextProps:传递进来的最新属性值
    console.log('componentwillReceiveProps:', this.props, nextProps)
    }
  • 触发 shouldComponentUpdate 周期函数

  • ... 其他步骤同组件更新

组件卸载

  1. 触发 componentwillUnmount
    1. 周期函数(组件销毁之前)
  2. 销毁

父子嵌套

tip

父子组件嵌套,处理机制上遵循深度优先原则:父组件在操作中,遇到子组件,一定是把子组件处理完,父组件才能继续处理

  • 父组件第一次渲染
    • 父 componentWillMount ->
    • 父 render ->
      • 子 componentWillMount -> 子 render -> 子componentDidMount ->
    • 父 componentDidMount
  • 父组件更新

    • 父 shouldComponentUpdate ->
    • 父 componentWillUpdate ->
    • 父 render ->
      • 子 componentWillReceiveProps -> 子 shouldComponentUpdate -> 子componentWillUpdate -> 子render -> 子 componentDidUpdate ->
    • 父 componentDidUpdate
  • 父组件销毁

    • 父 componentWillUnmount ->
      • 处理中 子componentWillUnmount -> 子销毁 ->
    • 父销毁

Class Component & Functional Component

  • 函数组件-静态组件
    • 组件第一次染完毕后,无法基于“内部的某些操作"让组件更新无法实现“自更新”
    • 如果调用它的父组件更新了,那么相关的子组件也定会更新,可能传递最新的属性值进来
    • 函数组件具备
      • 属性...其他状态等内容几乎没有J
    • 优势
      • 比类组件处理的机制简单,这样导致函数组件渲染速度更快!!
  • 类组件-动态组件

    • 组件在第-染完毕后,除了父组件更新可以触发其更新外,我们还可以通过:
      • this.setState修改状态或者 this.forceupdate 等方式让组件实现“自更新”
    • 类组件具备
      • 属性、状态、周期函数、ref...几乎组件应该有的东西它都具备
    • 优势
      • 功能强大! !
  • HOOKS组件

    • 推荐
      • 具备了函数组件和举件的各自优势、在函数组件的基础上,基HOOKS函数,让函数组件也可以拥有状态、周期函数等让函数组件也可以实现自更新[动态化]